/* Includes ------------------------------------------------------------------*/
#include "nfile.h"
#include "fcntl.h"
#include "lfs.h"
/* typedef -------------------------------------------------------------------*/
/* define --------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
int LittleFS_Open(struct FileObj *file, int oflag, va_list args);
size_t LittleFS_Write(struct FileObj *file, void *buf, size_t count);
size_t LittleFS_Read(struct FileObj *file, void *buf, size_t count);
int LittleFS_Lseek(struct FileObj *file, int offset, int whence);
int LittleFS_Close(struct FileObj *file);
int LittleFS_Fstat(struct FileObj *file, struct stat *status);

uint32_t LittleFS_FlagConvert(uint32_t flag);

struct FcntlOperation littlefsOps = {
    .open = LittleFS_Open,
    .write = LittleFS_Write,
    .read = LittleFS_Read,
    .lseek = LittleFS_Lseek,
    .close = LittleFS_Close,
    .fstat = LittleFS_Fstat
};

lfs_t lfs;
/* function prototypes -------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/
/*********************************************************************************************

 * file open

**********************************************************************************************/
int LittleFS_Open(struct FileObj *file, int oflag, va_list args)
{   
    int result = 0;
    oflag = LittleFS_FlagConvert(oflag);
    lfs_file_t *fileObj = (lfs_file_t *)malloc(sizeof(lfs_file_t));
    if(fileObj == NULL)
    {   return -105; }
    memset(fileObj, 0, sizeof(lfs_file_t));

    result = lfs_file_open(&lfs, fileObj, file->path, oflag);
    if(result == 0)
    {   file->obj = fileObj;    }
    else
    {   free(fileObj);  }
	return result;
}
/*********************************************************************************************

 * file write

**********************************************************************************************/
size_t LittleFS_Write(struct FileObj *file, void *buf, size_t count)
{   
    return lfs_file_write(&lfs, file->obj, buf, count);
}
/*********************************************************************************************

 * file read

**********************************************************************************************/
size_t LittleFS_Read(struct FileObj *file, void *buf, size_t count)
{   
	return lfs_file_read(&lfs, file->obj, buf, count);
}
/*********************************************************************************************

 * file lseek

**********************************************************************************************/
int LittleFS_Lseek(struct FileObj *file, int offset, int whence)
{
	return lfs_file_seek(&lfs, file->obj, offset, whence);
}
/*********************************************************************************************

 * file close

**********************************************************************************************/
int LittleFS_Close(struct FileObj *file)
{
	int result = lfs_file_close(&lfs, file->obj);
	free(file->obj);
	return result;
}
/*********************************************************************************************

 * file status

**********************************************************************************************/
int LittleFS_Fstat(struct FileObj *file, struct stat *status)
{
    struct lfs_info info;

    lfs_stat(&lfs, file->path, &info);
    status->st_size = info.size;

	return 0;
}

uint32_t LittleFS_FlagConvert(uint32_t flag)
{
    uint32_t flagConvert = 0;
    if((flag & O_RDONLY) != 0)
    {   flagConvert |= LFS_O_RDONLY;    }
    if((flag & O_WRONLY) != 0)
    {   flagConvert |= LFS_O_WRONLY;    }
    if((flag & O_CREAT) != 0)
    {   flagConvert |= LFS_O_CREAT;    }
    if((flag & O_EXCL) != 0)
    {   flagConvert |= LFS_O_EXCL;    }
    if((flag & O_TRUNC) != 0)
    {   flagConvert |= LFS_O_TRUNC;    }
    if((flag & O_APPEND) != 0)
    {   flagConvert |= LFS_O_APPEND;    }
    return flagConvert;
}
FILE_DRIVER_INSTALL(littlefs);
